golang切片边界自动检查
作者:matrix 被围观: 47 次 发布时间:2025-09-30 分类:Golang | 无评论 »
Golang 的切片边界自动检查(automatic slice bounds checking)是编译器在每次访问切片元素(比如 s[i])或进行切片操作(比如 s[a:b])时自动插入检查逻辑的安全机制,用于防止越界访问导致的崩溃。
自动检查机制
比如读取这个切片元素 s[i]
,在编译期间就会自动插入边界检查代码。
看到的代码:
func get(s []int, i int) int {
return s[i]
}
编译器自动检查后的伪代码(编译器隐式实现):
func get(s []int, i int) int {
// 自动插入的边界检查
if i < 0 || i >= len(s) {
panic("runtime error: index out of range")
}
return s[i]
}
编译器一般都会自动添加这种检查逻辑,除非编译器知道这个边界范围是安全的。
如果在循环中频繁访问切片元素的话就会导致不必要的开销。这种算是极致的性能优化了~ 目前还用不到😂
消除越界检查
没有主动消除的办法,只能显示告知编译器让其安全访问
source: https://cs.opensource.google/go/go/+/refs/tags/go1.23.2:src/cmd/compile/internal/bitvec/bv.go;l=161
func (dst BitVec) And(src1, src2 BitVec) {
if len(src1.B) == 0 {
return
}
_, _ = dst.B[len(src1.B)-1], src2.B[len(src1.B)-1] // hoist bounds checks out of the loop
for i, x := range src1.B {
dst.B[i] = x & src2.B[i]
}
}
第 5 行「hoist bounds checks out of the loop」注释位置的代码 目的就是把越界检查提升到循环外部,显式告知编译器 dst.B 和 src2.B 的长度至少和 src1.B 一样
,避免在每次迭代时检查。
如何确定有边界检查
go build -gcflags="-d=ssa/check_bce/debug=1" yourmain.go
run或者 build添加的-gcflags="-d=ssa/check_bce/debug=1"
可以看到是否存在边界检查
# command-line-arguments
./struct_11test.go:23:19: Found IsInBounds
Found IsInBounds
即表示存在自动边界检查